﻿using Abp.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;

namespace Hicap.AuthorizationServer.Core.Common.EFCore
{
    public interface IRepository<TEntity> where TEntity : class, IEntity, ISoftDelete
    {
        Task BatchInsertAsync(IList<TEntity> list);

        Task BatchUpdateAsync(IList<TEntity> list);

        Task BatchInsertOrUpdateAsync(IList<TEntity> list);

        int Count();

        int Count(Expression<Func<TEntity, bool>> predicate);

        Task<int> CountAsync();

        Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate);

        void Delete(Expression<Func<TEntity, bool>> predicate);

        void Delete(int id);

        void Delete(TEntity entity, bool isSoftDelete = true);

        Task DeleteAsync(Expression<Func<TEntity, bool>> predicate);

        Task DeleteAsync(int id);

        Task DeleteAsync(TEntity entity);

        Task EnsureCollectionLoadedAsync<TProperty>(TEntity entity, Expression<Func<TEntity, IEnumerable<TProperty>>> collectionExpression, CancellationToken cancellationToken) where TProperty : class;

        Task EnsurePropertyLoadedAsync<TProperty>(TEntity entity, Expression<Func<TEntity, TProperty>> propertyExpression, CancellationToken cancellationToken) where TProperty : class;

        TEntity FirstOrDefault(int id);

        Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate);

        Task<TEntity> FirstOrDefaultAsync(int id);

        TEntity Get(int id);

        Task<List<TEntity>> GetAllListAsync();

        Task<List<TEntity>> GetAllListAsync(Expression<Func<TEntity, bool>> predicate);

        Task<TEntity> GetAsync(int id);

        DbContext GetDbContext();

        IQueryable<TEntity> GetIncludingQuery(params Expression<Func<TEntity, object>>[] propertySelectors);

        IQueryable<TEntity> GetQuery();

        TEntity Insert(TEntity entity);

        int InsertAndGetId(TEntity entity);

        Task<int> InsertAndGetIdAsync(TEntity entity);

        Task<TEntity> InsertAsync(TEntity entity);

        TEntity InsertOrUpdate(TEntity entity);

        int InsertOrUpdateAndGetId(TEntity entity);

        Task<int> InsertOrUpdateAndGetIdAsync(TEntity entity);

        Task<TEntity> InsertOrUpdateAsync(TEntity entity);

        TEntity Load(int id);

        long LongCount();

        long LongCount(Expression<Func<TEntity, bool>> predicate);

        Task<long> LongCountAsync();

        Task<long> LongCountAsync(Expression<Func<TEntity, bool>> predicate);

        Task<TEntity> SingleAsync(Expression<Func<TEntity, bool>> predicate);

        TEntity Update(int id, Action<TEntity> updateAction);

        TEntity Update(TEntity entity);

        Task<TEntity> UpdateAsync(int id, Func<TEntity, Task> updateAction);

        Task<TEntity> UpdateAsync(TEntity entity);
    }
}